// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2001-2016, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

/**
 * Port From: ICU4C v1.8.1 : format : DateIntervalFormatTest Source File:
 * $ICU4CRoot/source/test/intltest/dtifmtts.cpp
 */
package com.ibm.icu.dev.test.format;

import com.ibm.icu.dev.test.CoreTestFmwk;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateIntervalFormat;
import com.ibm.icu.text.DateIntervalFormat.FormattedDateInterval;
import com.ibm.icu.text.DateIntervalInfo;
import com.ibm.icu.text.DateIntervalInfo.PatternInfo;
import com.ibm.icu.text.DateTimePatternGenerator;
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.DateInterval;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.Output;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import java.text.FieldPosition;
import java.text.Format.Field;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.model.MultipleFailureException;

@RunWith(JUnit4.class)
public class DateIntervalFormatTest extends CoreTestFmwk {

    /** */
    private static final ULocale SPANISH = new ULocale("es");

    /** */
    private static final ULocale LA_SPANISH = new ULocale("es-419");

    /**
     * Test format
     *
     * @throws MultipleFailureException
     */
    @Test
    public void TestFormat() throws MultipleFailureException {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/skeleton/interval_data
        // Note that from_data/to_data are specified using era names from root, for the calendar
        // specified by locale.
        String[] DATA = {
            "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data
            // test root
            "root",
            "CE 2007 11 10 10:10:10",
            "CE 2007 12 10 10:10:10",
            "yM",
            "2007-11\\u2009\\u2013\\u20092007-12",

            // test 'H' and 'h', using availableFormat in fallback
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 10 15:10:10",
            "Hms",
            "10:10:10\\u2009\\u2013\\u200915:10:10",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 10 15:10:10",
            "hms",
            "10:10:10\\u202FAM\\u2009\\u2013\\u20093:10:10\\u202FPM",

            // test skeleton with both date and time
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMyhm",
            "Nov 10, 2007, 10:10\\u202FAM\\u2009\\u2013\\u2009Nov 20, 2007, 10:10\\u202FAM",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 10 11:10:10",
            "dMMMyhm",
            "Nov 10, 2007, 10:10\\u2009\\u2013\\u200911:10\\u202FAM",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 10 11:10:10",
            "hms",
            "10:10:10\\u202FAM\\u2009\\u2013\\u200911:10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEEdMMMMy",
            "Wednesday, October 10, 2007\\u2009\\u2013\\u2009Friday, October 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMMMy",
            "October 10, 2007\\u2009\\u2013\\u2009October 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMMM",
            "October 10, 2007\\u2009\\u2013\\u2009October 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMMMy",
            "October 2007\\u2009\\u2013\\u2009October 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEEdMMMM",
            "Wednesday, October 10, 2007\\u2009\\u2013\\u2009Friday, October 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdMMMy",
            "Wed, Oct 10, 2007\\u2009\\u2013\\u2009Fri, Oct 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMMy",
            "Oct 10, 2007\\u2009\\u2013\\u2009Oct 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMM",
            "Oct 10, 2007\\u2009\\u2013\\u2009Oct 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMMy",
            "Oct 2007\\u2009\\u2013\\u2009Oct 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdMMM",
            "Wed, Oct 10, 2007\\u2009\\u2013\\u2009Fri, Oct 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdMy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMy",
            "10/10/2007\\u2009\\u2013\\u200910/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dM",
            "10/10/2007\\u2009\\u2013\\u200910/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "My",
            "10/2007\\u2009\\u2013\\u200910/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdM",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "d",
            "10/10/2007\\u2009\\u2013\\u200910/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "Ed",
            "10 Wed\\u2009\\u2013\\u200910 Fri",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "y",
            "2007\\u2009\\u2013\\u20092008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "M",
            "10/2007\\u2009\\u2013\\u200910/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMM",
            "Oct 2007\\u2009\\u2013\\u2009Oct 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMMM",
            "October 2007\\u2009\\u2013\\u2009October 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hm",
            "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hmv",
            "10/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hmz",
            "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "h",
            "10/10/2007, 10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hv",
            "10/10/2007, 10\\u202FAM PT\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM PT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hz",
            "10/10/2007, 10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM PDT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEddMMyyyy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EddMMy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hhmm",
            "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hhmmzz",
            "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hms",
            "10/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMMMMy",
            "O 10, 2007\\u2009\\u2013\\u2009O 10, 2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEEEdM",
            "W, 10/10/2007\\u2009\\u2013\\u2009F, 10/10/2008",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEdMMMMy",
            "Wednesday, October 10\\u2009\\u2013\\u2009Saturday, November 10, 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMMy",
            "October 10\\u2009\\u2013\\u2009November 10, 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMM",
            "October 10\\u2009\\u2013\\u2009November 10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMMMy",
            "October\\u2009\\u2013\\u2009November 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEdMMMM",
            "Wednesday, October 10\\u2009\\u2013\\u2009Saturday, November 10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdMMMy",
            "Wed, Oct 10\\u2009\\u2013\\u2009Sat, Nov 10, 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMy",
            "Oct 10\\u2009\\u2013\\u2009Nov 10, 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMM",
            "Oct 10\\u2009\\u2013\\u2009Nov 10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMMy",
            "Oct\\u2009\\u2013\\u2009Nov 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdMMM",
            "Wed, Oct 10\\u2009\\u2013\\u2009Sat, Nov 10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdMy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMy",
            "10/10/2007\\u2009\\u2013\\u200911/10/2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dM",
            "10/10\\u2009\\u2013\\u200911/10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "My",
            "10/2007\\u2009\\u2013\\u200911/2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdM",
            "Wed, 10/10\\u2009\\u2013\\u2009Sat, 11/10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "d",
            "10/10\\u2009\\u2013\\u200911/10",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "Ed",
            "10 Wed\\u2009\\u2013\\u200910 Sat",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "y",
            "2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "M",
            "10\\u2009\\u2013\\u200911",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMM",
            "Oct\\u2009\\u2013\\u2009Nov",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMMM",
            "October\\u2009\\u2013\\u2009November",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hm",
            "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hmv",
            "10/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hmz",
            "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PST",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "h",
            "10/10/2007, 10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hv",
            "10/10/2007, 10\\u202FAM PT\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM PT",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hz",
            "10/10/2007, 10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM PST",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEddMMyyyy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EddMMy",
            "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hhmm",
            "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hhmmzz",
            "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PST",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hms",
            "10/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10:10:10\\u202FAM",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMMMy",
            "O 10\\u2009\\u2013\\u2009N 10, 2007",
            "en",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEEdM",
            "W, 10/10\\u2009\\u2013\\u2009S, 11/10",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMMMy",
            "Saturday, November 10\\u2009\\u2013\\u2009Tuesday, November 20, 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMMy",
            "November 10\\u2009\\u2013\\u200920, 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMM",
            "November 10\\u2009\\u2013\\u200920",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMMMy",
            "November 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMMM",
            "Saturday, November 10\\u2009\\u2013\\u2009Tuesday, November 20",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMMMy",
            "Sat, Nov 10\\u2009\\u2013\\u2009Tue, Nov 20, 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMM",
            "Nov 10\\u2009\\u2013\\u200920",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMMy",
            "Nov 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMMM",
            "Sat, Nov 10\\u2009\\u2013\\u2009Tue, Nov 20",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMy",
            "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMy",
            "11/10/2007\\u2009\\u2013\\u200911/20/2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dM",
            "11/10\\u2009\\u2013\\u200911/20",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "My",
            "11/2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdM",
            "Sat, 11/10\\u2009\\u2013\\u2009Tue, 11/20",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "d",
            "10\\u2009\\u2013\\u200920",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "Ed",
            "10 Sat\\u2009\\u2013\\u200920 Tue",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "M",
            "11",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMM",
            "Nov",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hm",
            "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hmv",
            "11/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PT",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hmz",
            "11/10/2007, 10:10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PST",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hz",
            "11/10/2007, 10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10\\u202FAM PST",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEddMMyyyy",
            "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EddMMy",
            "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hhmm",
            "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hms",
            "11/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10:10\\u202FAM",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMMMy",
            "N 10\\u2009\\u2013\\u200920, 2007",
            "en",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEEdM",
            "S, 11/10\\u2009\\u2013\\u2009T, 11/20",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEdMMMMy",
            "Wednesday, January 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMMMy",
            "January 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMMM",
            "January 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "MMMMy",
            "January 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEdMMMM",
            "Wednesday, January 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMMy",
            "Jan 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMM",
            "Jan 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "MMMy",
            "Jan 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EdMMM",
            "Wed, Jan 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EdMy",
            "Wed, 1/10/2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMy",
            "1/10/2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dM",
            "1/10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EdM",
            "Wed, 1/10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "d",
            "10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "Ed",
            "10 Wed",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "y",
            "2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "MMM",
            "Jan",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "MMMM",
            "January",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hm",
            "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hmz",
            "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM PST",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "h",
            "10\\u202FAM\\u2009\\u2013\\u20092\\u202FPM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hv",
            "10\\u202FAM\\u2009\\u2013\\u20092\\u202FPM PT",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hz",
            "10\\u202FAM\\u2009\\u2013\\u20092\\u202FPM PST",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEddMMyyyy",
            "Wed, 01/10/2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hhmm",
            "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hhmmzz",
            "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM PST",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMMMMy",
            "J 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEEdM",
            "W, 1/10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EEEEdMMMMy",
            "Wednesday, January 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "dMMMMy",
            "January 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "MMMMy",
            "January 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EdMMMy",
            "Wed, Jan 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "dMMMy",
            "Jan 10, 2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "dMMM",
            "Jan 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EdMMM",
            "Wed, Jan 10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EdMy",
            "Wed, 1/10/2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "dM",
            "1/10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EdM",
            "Wed, 1/10",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "y",
            "2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "MMM",
            "Jan",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hm",
            "10:00\\u2009\\u2013\\u200910:20\\u202FAM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hmv",
            "10:00\\u2009\\u2013\\u200910:20\\u202FAM PT",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "h",
            "10\\u202FAM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hz",
            "10\\u202FAM PST",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EddMMy",
            "Wed, 01/10/2007",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hhmm",
            "10:00\\u2009\\u2013\\u200910:20\\u202FAM",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hhmmzz",
            "10:00\\u2009\\u2013\\u200910:20\\u202FAM PST",
            "en",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hms",
            "10:00:10\\u202FAM\\u2009\\u2013\\u200910:20:10\\u202FAM",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "dMMMM",
            "January 10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EEEEdMMMM",
            "Wednesday, January 10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EdMMMy",
            "Wed, Jan 10, 2007",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "dMMM",
            "Jan 10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EdMMM",
            "Wed, Jan 10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "dM",
            "1/10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "My",
            "1/2007",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EdM",
            "Wed, 1/10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "d",
            "10",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "Ed",
            "10 Wed",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "y",
            "2007",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "M",
            "1",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "MMM",
            "Jan",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "MMMM",
            "January",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hm",
            "10:10\\u202FAM",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hmv",
            "10:10\\u202FAM PT",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hmz",
            "10:10\\u202FAM PST",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "h",
            "10\\u202FAM",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hz",
            "10\\u202FAM PST",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hhmmzz",
            "10:10\\u202FAM PST",
            "en",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hms",
            "10:10:10\\u202FAM\\u2009\\u2013\\u200910:10:20\\u202FAM",
            "en",
            "CE 2007 01 01 22:00:00",
            "CE 2007 01 01 23:00:00",
            "yMMMMdHm",
            "January 1, 2007, 22:00\\u2009\\u2013\\u200923:00",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEEdMMMMy",
            "2007\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e09\\u81f32008\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e94",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hm",
            "2007/10/10 \\u4e0a\\u534810:10 \\u2013 2008/10/10 \\u4e0a\\u534810:10",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMMy",
            "2007\\u5E74\\u5341\\u670810\\u65E5\\u2009\\u2013\\u2009\\u5341\\u4E00\\u670810\\u65E5",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMM",
            "10\\u670810\\u65e5\\u81f311\\u670810\\u65e5",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMMMy",
            "2007\\u5e7410\\u6708 \\u2013 11\\u6708",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEdMMMM",
            "10\\u670810\\u65e5\\u661f\\u671f\\u4e09\\u81f311\\u670810\\u65e5\\u661f\\u671f\\u516d",
            "zh",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hmv",
            "2007/10/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:10 \\u2013 2007/11/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:10",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMMMy",
            "2007\\u5E74\\u5341\\u4E00\\u670810\\u65E5\\u661F\\u671F\\u516D\\u2009\\u2013\\u2009\\u5341\\u4E00\\u670820\\u65E5\\u661F\\u671F\\u4E8C",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMMy",
            "2007\\u5e74\\u5341\\u4e00\\u670810\\u65e5\\u2009\\u2013\\u200920\\u65e5",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMM",
            "11\\u670810\\u65e5\\u81f320\\u65e5",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMMMy",
            "2007\\u5E7411\\u6708", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMMM",
            "11\\u670810\\u65e5\\u661f\\u671f\\u516d\\u81f320\\u65e5\\u661f\\u671f\\u4e8c",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMMM",
            "11\\u670810\\u65e5\\u5468\\u516d\\u81f320\\u65e5\\u5468\\u4e8c",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMy",
            "2007/11/10\\u5468\\u516d\\u81f32007/11/20\\u5468\\u4e8c",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMy",
            "2007/11/10 \\u2013 2007/11/20",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dM",
            "11/10 \\u2013 11/20",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "My",
            "2007/11",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdM",
            "11/10\\u5468\\u516d\\u81f311/20\\u5468\\u4e8c",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "d",
            "10\\u201320\\u65e5",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "y",
            "2007\\u5E74", // (fixed expected result per ticket:6626:)
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "M",
            "11\\u6708",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMM",
            "11\\u6708", // (fixed expected result per ticket 6872<-6626 and others)
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMMM",
            "\\u5341\\u4E00\\u6708", // (fixed expected result per ticket 6872<-6626 and others)
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hmz",
            "2007/11/10 GMT-8\\u4e0a\\u534810:10 \\u2013 2007/11/20 GMT-8\\u4e0a\\u534810:10",
            "zh",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "h",
            "2007/11/10 \\u4e0a\\u534810\\u65f6 \\u2013 2007/11/20 \\u4e0a\\u534810\\u65f6",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEdMMMMy",
            "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per
            // ticket 6872<-6626)
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hm",
            "\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hmv",
            "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F3\\u4E0B\\u53482:10",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hmz",
            "GMT-8\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "h",
            "\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hv",
            "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810\\u65F6\\u81F3\\u4E0B\\u53482\\u65F6",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hz",
            "GMT-8\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "dMMMM",
            "1\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hm",
            "\\u4e0a\\u534810:00\\u81f310:20",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hmv",
            "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F310:20",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "h",
            "\\u4e0a\\u534810\\u65f6",
            "zh",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hz",
            "GMT-8\\u4e0a\\u534810\\u65f6",
            "zh",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EEEEdMMMMy",
            "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per
            // ticket 6872<-6626)
            "zh",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hm",
            "\\u4e0a\\u534810:10",
            "zh",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "h",
            "\\u4e0a\\u534810\\u65f6",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEEdMMMy",
            "Mittwoch, 10. Okt. 2007\\u2009\\u2013\\u2009Freitag, 10. Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMMy",
            "10. Okt. 2007\\u2009\\u2013\\u200910. Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMMM",
            "10. Okt. 2007\\u2009\\u2013\\u200910. Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMMy",
            "Okt. 2007\\u2009\\u2013\\u2009Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EEEdMMM",
            "Mi., 10. Okt. 2007\\u2009\\u2013\\u2009Fr., 10. Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdMy",
            "Mi., 10.10.2007\\u2009\\u2013\\u2009Fr., 10.10.2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dMy",
            "10.10.2007\\u2009\\u2013\\u200910.10.2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "dM",
            "10.10.2007\\u2009\\u2013\\u200910.10.2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "My",
            "10/2007\\u2009\\u2013\\u200910/2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "EdM",
            "Mi., 10.10.2007\\u2009\\u2013\\u2009Fr., 10.10.2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "d",
            "10.10.2007\\u2009\\u2013\\u200910.10.2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "y",
            "2007\\u20132008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "M",
            "10/2007\\u2009\\u2013\\u200910/2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "MMM",
            "Okt. 2007\\u2009\\u2013\\u2009Okt. 2008",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "hm",
            "10.10.2007, 10:10\\u202FAM\\u2009\\u2013\\u200910.10.2008, 10:10\\u202FAM",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2008 10 10 10:10:10",
            "jm",
            "10.10.2007, 10:10\\u2009\\u2013\\u200910.10.2008, 10:10",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEdMMMy",
            "Mittwoch, 10. Okt.\\u2009\\u2013\\u2009Samstag, 10. Nov. 2007",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMMy",
            "10. Okt.\\u2009\\u2013\\u200910. Nov. 2007",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dMMM",
            "10. Okt.\\u2009\\u2013\\u200910. Nov.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMMy",
            "Okt.\\u2013Nov. 2007",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EEEEdMMM",
            "Mittwoch, 10. Okt.\\u2009\\u2013\\u2009Samstag, 10. Nov.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdMy",
            "Mi., 10.10.\\u2009\\u2013\\u2009Sa., 10.11.2007",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "dM",
            "10.10.\\u2009\\u2013\\u200910.11.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "My",
            "10/2007\\u2009\\u2013\\u200911/2007",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "EdM",
            "Mi., 10.10.\\u2009\\u2013\\u2009Sa., 10.11.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "d",
            "10.10.\\u2009\\u2013\\u200910.11.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "M",
            "10–11",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "MMM",
            "Okt.\\u2013Nov.",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hmv",
            "10.10.2007, 10:10\\u202FAM Los Angeles (Ortszeit)\\u2009\\u2013\\u200910.11.2007, 10:10\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "jmv",
            "10.10.2007, 10:10 Los Angeles (Ortszeit)\\u2009\\u2013\\u200910.11.2007, 10:10 Los Angeles (Ortszeit)",
            "de",
            "CE 2007 10 10 10:10:10",
            "CE 2007 11 10 10:10:10",
            "hms",
            "10.10.2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200910.11.2007, 10:10:10\\u202FAM",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMMy",
            "Samstag, 10.\\u2009\\u2013\\u2009Dienstag, 20. Nov. 2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMMy",
            "10.\\u201320. Nov. 2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMMM",
            "10.\\u201320. Nov.",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "MMMy",
            "Nov. 2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EEEEdMMM",
            "Samstag, 10.\\u2009\\u2013\\u2009Dienstag, 20. Nov.",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdMy",
            "Sa., 10.\\u2009\\u2013\\u2009Di., 20.11.2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dMy",
            "10.\\u201320.11.2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "dM",
            "10.\\u201320.11.",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "My",
            "11/2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "EdM",
            "Sa., 10.\\u2009\\u2013\\u2009Di., 20.11.",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "d",
            "10.\\u201320.",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "y",
            "2007",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "M",
            "11",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "hmv",
            "10.11.2007, 10:10\\u202FAM Los Angeles (Ortszeit)\\u2009\\u2013\\u200920.11.2007, 10:10\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 11 10 10:10:10",
            "CE 2007 11 20 10:10:10",
            "jmv",
            "10.11.2007, 10:10 Los Angeles (Ortszeit)\\u2009\\u2013\\u200920.11.2007, 10:10 Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEdMMMy",
            "Mittwoch, 10. Jan. 2007",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMMy",
            "10. Jan. 2007",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "dMMM",
            "10. Jan.",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "MMMy",
            "Jan. 2007",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "EEEEdMMM",
            "Mittwoch, 10. Jan.",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "hmz",
            "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM GMT-8",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 14:10:10",
            "h",
            "10 AM – 2 PM",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "EEEEdMMM",
            "Mittwoch, 10. Jan.",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hm",
            "10:00\\u201310:20\\u202FAM",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hmv",
            "10:00\\u201310:20\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hmz",
            "10:00\\u201310:20\\u202FAM GMT-8",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "h",
            "10\\u202FAM",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hv",
            "10\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:00:10",
            "CE 2007 01 10 10:20:10",
            "hz",
            "10\\u202FAM GMT-8",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "EEEEdMMMy",
            "Mittwoch, 10. Jan. 2007",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hm",
            "10:10\\u202FAM",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "jm",
            "10:10",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hmv",
            "10:10\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "jmv",
            "10:10 Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hmz",
            "10:10\\u202FAM GMT-8",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "jmz",
            "10:10 GMT-8",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "h",
            "10\\u202FAM",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hv",
            "10\\u202FAM Los Angeles (Ortszeit)",
            "de",
            "CE 2007 01 10 10:10:10",
            "CE 2007 01 10 10:10:20",
            "hz",
            "10\\u202FAM GMT-8",

            // Thai (default calendar buddhist)

            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "EEEEdMMMy",
            "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2550 \\u2013 \\u0E27\\u0E31\\u0E19\\u0E28\\u0E38\\u0E01\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "dMMM",
            "10 \\u0E15.\\u0E04. 2550 \\u2013 10 \\u0E15.\\u0E04. 2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "MMMy",
            "\\u0E15.\\u0E04. 2550 \\u2013 \\u0E15.\\u0E04. 2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "EdMy",
            "\\u0E1E\\u0E38\\u0E18 10/10/2550 \\u2013 \\u0E28\\u0E38\\u0E01\\u0E23\\u0E4C 10/10/2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "dMy",
            "10/10/2550 \\u2013 10/10/2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "My",
            "10/2550 \\u2013 10/2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "EdM",
            "\\u0E1E\\u0E38\\u0E18 10/10/2550 \\u2013 \\u0E28\\u0E38\\u0E01\\u0E23\\u0E4C 10/10/2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "y",
            "2550\\u20132551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2551 10 10 10:10:10",
            "M",
            "10/2550 \\u2013 10/2551",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "EEEEdMMMy",
            "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. \\u2013 \\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E1E.\\u0E22. 2550",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "dMMM",
            "10 \\u0E15.\\u0E04. \\u2013 10 \\u0E1E.\\u0E22.",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "MMMy",
            "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22. 2550",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "dM",
            "10/10 \\u2013 10/11",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "My",
            "10/2550 \\u2013 11/2550",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "d",
            "10/10 \\u2013 10/11",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "y",
            "\\u0e1e.\\u0e28. 2550",
            "th",
            "BE 2550 10 10 10:10:10",
            "BE 2550 11 10 10:10:10",
            "MMM",
            "\u0E15.\u0E04.\u2013\u0E1E.\u0E22.",

            // Tests for Japanese calendar with eras, including new era in 2019 (Heisei 31 through
            // April 30, then new era)

            "en-u-ca-japanese",
            "H 31 03 15 09:00:00",
            "H 31 04 15 09:00:00",
            "GyMMMd",
            "Mar 15\u2009\u2013\u2009Apr 15, 31 Heisei",
            "en-u-ca-japanese",
            "H 31 03 15 09:00:00",
            "H 31 04 15 09:00:00",
            "GGGGGyMd",
            "3/15/31\u2009\u2013\u20094/15/31 H",
            "en-u-ca-japanese",
            "S 64 01 05 09:00:00",
            "H 1 01 15 09:00:00",
            "GyMMMd",
            "Jan 5, 64 Sh\u014Dwa\u2009\u2013\u2009Jan 15, 1 Heisei",
            "en-u-ca-japanese",
            "S 64 01 05 09:00:00",
            "H 1 01 15 09:00:00",
            "GGGGGyMd",
            "1/5/64 S\u2009\u2013\u20091/15/1 H",
            "en-u-ca-japanese",
            "H 31 04 15 09:00:00",
            DateFormat.JP_ERA_2019_NARROW + " 1 05 15 09:00:00",
            "GyMMMd",
            "Apr 15, 31 Heisei\u2009\u2013\u2009May 15, 1 " + DateFormat.JP_ERA_2019_ROOT,
            "en-u-ca-japanese",
            "H 31 04 15 09:00:00",
            DateFormat.JP_ERA_2019_NARROW + " 1 05 15 09:00:00",
            "GGGGGyMd",
            "4/15/31 H\u2009\u2013\u20095/15/1 " + DateFormat.JP_ERA_2019_NARROW,
            "ja-u-ca-japanese",
            "H 31 03 15 09:00:00",
            "H 31 04 15 09:00:00",
            "GyMMMd",
            "\u5E73\u621031\u5E743\u670815\u65E5\uFF5E4\u670815\u65E5",
            "ja-u-ca-japanese",
            "H 31 03 15 09:00:00",
            "H 31 04 15 09:00:00",
            "GGGGGyMd",
            "H31/03/15\uFF5E31/04/15",
            "ja-u-ca-japanese",
            "S 64 01 05 09:00:00",
            "H 1 01 15 09:00:00",
            "GyMMMd",
            "\u662D\u548C64\u5E741\u67085\u65E5\uFF5E\u5E73\u6210\u5143\u5E741\u670815\u65E5",
            "ja-u-ca-japanese",
            "S 64 01 05 09:00:00",
            "H 1 01 15 09:00:00",
            "GGGGGyMd",
            "S64/01/05\uFF5EH1/01/15",
            "ja-u-ca-japanese",
            "H 31 04 15 09:00:00",
            DateFormat.JP_ERA_2019_NARROW + " 1 05 15 09:00:00",
            "GGGGGyMd",
            "H31/04/15\uFF5E" + DateFormat.JP_ERA_2019_NARROW + "1/05/15",
        };
        expect(DATA, DATA.length);
    }

    /**
     * Test handling of hour and day period metacharacters
     *
     * @throws MultipleFailureException
     */
    @Test
    public void TestHourMetacharacters() throws MultipleFailureException {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/skeleton/interval_data
        // Note that from_data/to_data are specified using era names from root, for the calendar
        // specified by locale.
        String[] DATA = {
            "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data

            // This test is for tickets ICU-21154, ICU-21155, and ICU-21156 and is intended to
            // verify
            // that all of the special skeleton characters for hours and day periods work as
            // expected
            // with date intervals:
            // - If a, b, or B is included in the skeleton, it correctly sets the length of the
            // day-period field
            // - If k or K is included, it behaves the same as H or h, except for the difference in
            // the actual
            //   number used for the hour.
            // - If j is included, it behaves the same as either h or H as appropriate, and multiple
            // j's have the
            //   intended effect on the length of the day period field (if there is one)
            // - If J is included, it correctly suppresses the day period field if j would include
            // it
            // - If C is included, it behaves the same as j and brings up the correct day period
            // field
            // - In all cases, if the day period of both ends of the range is the same, you only see
            // it once

            // baseline (h and H)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hh",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "HH",
            "00–01 Uhr",

            // k and K (ICU-21154 and ICU-21156)
            // (should behave the same as h and H if not overridden in locale ID)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "KK",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "kk",
            "00\\u201301 Uhr",
            // (overriding hour cycle in locale ID should affect both h and K [or both H and k])
            "en-u-hc-h11",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hh",
            "0\\u2009\\u2013\\u20091\\u202FAM",
            "en-u-hc-h11",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "KK",
            "0\\u2009\\u2013\\u20091\\u202FAM",
            "de-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "HH",
            "24–01 Uhr",
            "de-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "kk",
            "24–01 Uhr",
            // (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT
            // affect h and K)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "HH",
            "00\\u2009\\u2013\\u200901",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "kk",
            "00\\u2009\\u2013\\u200901",
            "en-u-hc-h11",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "HH",
            "00\\u2009\\u2013\\u200901",
            "en-u-hc-h11",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "kk",
            "00\\u2009\\u2013\\u200901",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hh",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "KK",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "de-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hh",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "de-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "KK",
            "12\\u2009\\u2013\\u20091\\u202FAM",

            // different lengths of the 'a' field
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "ha",
            "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "ha",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 12:00:00",
            "haaaaa",
            "10\\u202Fa\\u2009\\u2013\\u200912\\u202Fp",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "haaaaa",
            "12\\u2009\\u2013\\u20091\\u202Fa",

            // j (ICU-21155)
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jj",
            "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jj",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jjjjj",
            "10\\u202Fa\\u2009\\u2013\\u20091\\u202Fp",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jjjjj",
            "12\\u2009\\u2013\\u20091\\u202Fa",
            "de",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jj",
            "10–13 Uhr",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jj",
            "00–01 Uhr",
            "de",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jjjjj",
            "10–13 Uhr",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jjjjj",
            "00–01 Uhr",

            // b and B
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 12:00:00",
            "hb",
            "10\\u202FAM\\u2009\\u2013\\u200912\\u202Fnoon",
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 12:00:00",
            "hbbbbb",
            "10\\u202Fa\\u2009\\u2013\\u200912\\u202Fn",
            "en",
            "CE 2010 09 27 13:00:00",
            "CE 2010 09 27 14:00:00",
            "hb",
            "1\\u2009\\u2013\\u20092\\u202FPM",
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "hB",
            "10 in the morning\\u2009\\u2013\\u20091 in the afternoon",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hB",
            "12\\u2009\\u2013\\u20091 in the morning",

            // J
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "J",
            "10\\u2009\\u2013\\u20091",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "J",
            "12\\u2009\\u2013\\u20091",
            "de",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "J",
            "10–13 Uhr",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "J",
            "00–01 Uhr",

            // C
            // (for English and German, C should do the same thing as j)
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CC",
            "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CC",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "en",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CCCCC",
            "10\\u202Fa\\u2009\\u2013\\u20091\\u202Fp",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CCCCC",
            "12\\u2009\\u2013\\u20091\\u202Fa",
            "de",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CC",
            "10–13 Uhr",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CC",
            "00–01 Uhr",
            "de",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CCCCC",
            "10–13 Uhr",
            "de",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CCCCC",
            "00–01 Uhr",
            // (for zh_HK and hi_IN, j maps to ha, but C maps to hB)
            "zh_HK",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jj",
            "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
            "zh_HK",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jj",
            "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
            "zh_HK",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "hB",
            "\\u4E0A\\u534810\\u6642 \\u2013 \\u4E0B\\u53481\\u6642",
            "zh_HK",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hB",
            "\\u51CC\\u666812\\u20131\\u6642",
            "zh_HK",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CC",
            "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
            "zh_HK",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CC",
            "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
            "hi_IN",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "jj",
            "10\\u202Fam\\u2009\\u2013\\u20091\\u202Fpm",
            "hi_IN",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jj",
            "12\\u20131\\u202Fam",
            "hi_IN",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "hB",
            "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
            "hi_IN",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hB",
            "\\u0930\\u093E\\u0924 12\\u20131",
            "hi_IN",
            "CE 2010 09 27 10:00:00",
            "CE 2010 09 27 13:00:00",
            "CC",
            "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
            "hi_IN",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "CC",
            "\\u0930\\u093E\\u0924 12\\u20131",

            // regression test for ICU-21342
            "en-gb-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 10:00:00",
            "kk",
            "24\\u201310",
            "en-gb-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 11:00:00",
            "kk",
            "24\\u201311",
            "en-gb-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 12:00:00",
            "kk",
            "24\\u201312",
            "en-gb-u-hc-h24",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 13:00:00",
            "kk",
            "24\\u201313",

            // regression test for ICU-21343
            "de",
            "CE 2010 09 27 01:00:00",
            "CE 2010 09 27 10:00:00",
            "KK",
            "1\\u2009\\u2013\\u200910\\u202FAM",

            // regression test for ICU-21154 (single-date ranges should use the same hour cycle as
            // multi-date ranges)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 00:00:00",
            "hh",
            "12\\u202FAM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "hh",
            "12\\u2009\\u2013\\u20091\\u202FAM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 00:00:00",
            "KK",
            "12\\u202FAM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "KK",
            "12\\u2009\\u2013\\u20091\\u202FAM", // (this was producing "0 - 1 AM" before)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 00:00:00",
            "jj",
            "12\\u202FAM",
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "jj",
            "12\\u2009\\u2013\\u20091\\u202FAM",

            // regression test for ICU-21984 (multiple day-period characters in date-interval
            // patterns)
            "en",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "MMMdhhmma",
            "Sep 27, 12:00\\u2009\\u2013\\u20091:00\\u202FAM",
            "sq",
            "CE 2010 09 27 00:00:00",
            "CE 2010 09 27 01:00:00",
            "Bhm",
            "12:00\\u2009\\u2013\\u20091:00 e nat\\u00EBs",
        };
        expect(DATA, DATA.length);
    }

    private void expect(String[] data, int data_length) throws MultipleFailureException {
        int i = 0;
        String pattern = data[i++];

        List<Throwable> allErrs = new LinkedList<>();

        while (i < data_length) {
            String locName = data[i++];
            String datestr = data[i++];
            String datestr_2 = data[i++];

            ULocale loc = new ULocale(locName);
            Calendar defCal = Calendar.getInstance(loc);
            String calType = defCal.getType();

            ULocale refLoc = ULocale.ROOT.setKeywordValue("calendar", calType);
            SimpleDateFormat ref = new SimpleDateFormat(pattern, refLoc);
            // 'f'
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch (ParseException e) {
                errln("parse exception" + e);
                i += 2; // skip the rest of the strings for this item
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(), date_2.getTime());
            String oneSkeleton = data[i++];
            DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(oneSkeleton, loc);
            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv);
            if (!formatted.equals(Utility.unescape(expected))) {
                allErrs.add(
                        new AssertionError(
                                "\""
                                        + locName
                                        + "\\"
                                        + oneSkeleton
                                        + "\\"
                                        + datestr
                                        + "\\"
                                        + datestr_2
                                        + "\"\t expected: "
                                        + expected
                                        + "\tgot: "
                                        + formatted
                                        + "\n"));
            }
        }
        // throw 1 exception wth all of the errs
        if (!allErrs.isEmpty()) {
            throw new MultipleFailureException(allErrs);
        }
    }

    /*
     * Test format using user defined DateIntervalInfo
     */
    @Test
    public void TestFormatUserDII() {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/interval_data
        String[] DATA = {
            "yyyy MM dd HH:mm:ss",
            "en",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "Oct 10, 2007 --- Oct 10, 2008",
            "en",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 Oct 10 - Nov 2007",
            "en",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "Nov 10, 2007 --- Nov 20, 2007",
            "en",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "Jan 10, 2007",
            "en",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "Jan 10, 2007",
            "en",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "Jan 10, 2007",
            "zh",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "2007\\u5e7410\\u670810\\u65e5 --- 2008\\u5e7410\\u670810\\u65e5",
            "zh",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "2007\\u5e7411\\u670810\\u65e5 --- 2007\\u5e7411\\u670820\\u65e5",
            "zh",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket 6872<-6626)
            "de",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "10. Okt. 2007 --- 10. Okt. 2008",
            "de",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 Okt. 10 - Nov. 2007",
            "de",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "10. Nov. 2007 --- 20. Nov. 2007",
            "de",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "10. Jan. 2007",
            "de",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "10. Jan. 2007",
            "de",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "10. Jan. 2007",
            "es",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "10 oct 2007 --- 10 oct 2008",
            "es",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 oct 10 - nov 2007",
            "es",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "10 nov 2007 --- 20 nov 2007",
            "es",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "10 ene 2007",
            "es",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "10 ene 2007",
            "es",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "10 ene 2007",
        };
        expectUserDII(DATA, DATA.length);
    }

    private void expectUserDII(String[] data, int data_length) {
        int i = 1;
        while (i < data_length) {
            String locName = data[i++];
            ULocale loc = new ULocale(locName);
            SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch (ParseException e) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(), date_2.getTime());

            DateIntervalInfo dtitvinf = new DateIntervalInfo();
            dtitvinf.setFallbackIntervalPattern("{0} --- {1}");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy MMM d - MMM y");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm");
            DateIntervalFormat dtitvfmt =
                    DateIntervalFormat.getInstance(DateFormat.YEAR_ABBR_MONTH_DAY, loc, dtitvinf);
            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv);
            if (!formatted.equals(Utility.unescape(expected))) {
                errln(
                        "userDII: \""
                                + locName
                                + "\\"
                                + datestr
                                + "\\"
                                + datestr_2
                                + "\"\t expected: "
                                + expected
                                + "\tgot: "
                                + formatted
                                + "\n");
            }
        }
    }

    /*
     * Test format using DisplayContext
     */
    @Test
    public void TestContext() {
        final long startDate = 1285599629000L; // 2010-Sep-27 0800 in America/Los_Angeles
        final long day = 24 * 60 * 60 * 1000; // milliseconds in a day

        class DateIntervalContextItem {
            public String locale;
            public String skeleton;
            public DisplayContext context;
            public long deltaDate;
            public String expectResult;

            // Simple constructor
            public DateIntervalContextItem(
                    String loc, String skel, DisplayContext ctxt, long delta, String expect) {
                locale = loc;
                skeleton = skel;
                context = ctxt;
                deltaDate = delta;
                expectResult = expect;
            }
        }
        ;

        final DateIntervalContextItem[] testItems = {
            new DateIntervalContextItem(
                    "cs",
                    "MMMEd",
                    DisplayContext.CAPITALIZATION_NONE,
                    60 * day,
                    "po 27. 9.\u2009–\u2009pá 26. 11."),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_NONE,
                    60 * day,
                    "září–listopad 2010"),
            new DateIntervalContextItem(
                    "cs", "yMMMM", DisplayContext.CAPITALIZATION_NONE, 1 * day, "září 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "MMMEd",
                    DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE,
                    60 * day,
                    "Po 27. 9.\u2009–\u2009pá 26. 11."),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE,
                    60 * day,
                    "Září–listopad 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE,
                    1 * day,
                    "Září 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "MMMEd",
                    DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,
                    60 * day,
                    "Po 27. 9.\u2009–\u2009pá 26. 11."),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,
                    60 * day,
                    "Září–listopad 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU,
                    1 * day,
                    "Září 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "MMMEd",
                    DisplayContext.CAPITALIZATION_FOR_STANDALONE,
                    60 * day,
                    "po 27. 9.\u2009–\u2009pá 26. 11."),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_STANDALONE,
                    60 * day,
                    "září–listopad 2010"),
            new DateIntervalContextItem(
                    "cs",
                    "yMMMM",
                    DisplayContext.CAPITALIZATION_FOR_STANDALONE,
                    1 * day,
                    "září 2010"),
        };

        for (DateIntervalContextItem item : testItems) {
            DateIntervalFormat difmt =
                    DateIntervalFormat.getInstance(item.skeleton, new ULocale(item.locale));
            difmt.setTimeZone(TimeZone.getFrozenTimeZone("America/Los_Angeles"));

            difmt.setContext(item.context);
            DisplayContext getContext = difmt.getContext(DisplayContext.Type.CAPITALIZATION);
            if (getContext != item.context) {
                errln(
                        "For locale "
                                + item.locale
                                + ", skeleton "
                                + item.skeleton
                                + ", context "
                                + item.context
                                + ": getContext returned "
                                + getContext);
            }
            DateInterval interval = new DateInterval(startDate, startDate + item.deltaDate);
            FieldPosition pos = new FieldPosition(0);
            StringBuffer getResult = new StringBuffer();
            difmt.format(interval, getResult, pos);
            if (!getResult.toString().equals(item.expectResult)) {
                errln(
                        "For locale "
                                + item.locale
                                + ", skeleton "
                                + item.skeleton
                                + ", context "
                                + item.context
                                + ": expected "
                                + item.expectResult
                                + ", got "
                                + getResult.toString());
            }
        }
    }

    /*
     * Test format using user defined DateIntervalInfo
     */
    @Test
    public void TestFormatCLDR() {
        // first item is date pattern
        // followed by a group of locale/from_data/to_data/interval_data
        String[] DATA = {
            "yyyy MM dd HH:mm:ss",
            "en",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "all diff",
            "en",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 diff Oct 10 - Nov 2007",
            "en",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "2007 Nov 10 ~ 20",
            "en",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "Jan 10, 2007",
            "en",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "Jan 10, 2007",
            "en",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "Jan 10, 2007",
            "zh",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "all diff",
            "zh",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 diff 10\\u6708 10 - 11\\u6708 2007",
            "zh",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "2007 11\\u6708 10 ~ 20",
            "zh",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)
            "zh",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
            "2007\u5E741\\u670810\u65E5", // (fixed expected result per ticket 6872<-6626)
        };
        expectUserCLDR(DATA, DATA.length);
    }

    private void expectUserCLDR(String[] data, int data_length) {
        int i = 1;
        while (i < data_length) {
            String locName = data[i++];
            ULocale loc = new ULocale(locName);
            SimpleDateFormat ref = new SimpleDateFormat(data[0], loc);
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date, date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch (ParseException e) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(), date_2.getTime());

            DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("yyyyMMMdd", loc);
            // DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("yMd");
            // SimpleDateFormat dtfmt = new SimpleDateFormat("yyyy 'year' MMM 'month' dd 'day'",
            // loc);
            // dtitvfmt.setDateFormat(dtfmt);
            DateIntervalInfo dtitvinf = new DateIntervalInfo();
            dtitvinf.setFallbackIntervalPattern("{0} --- {1}");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.YEAR, "'all diff'");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy 'diff' MMM d - MMM y");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.DATE, "yyyy MMM d ~ d");
            dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMMd HH:mm ~ HH:mm");
            dtitvfmt.setDateIntervalInfo(dtitvinf);
            FieldPosition pos = new FieldPosition(0);
            StringBuffer str = new StringBuffer("");
            DateFormat dtfmt = dtitvfmt.getDateFormat();
            Calendar fromCalendar = dtfmt.getCalendar().clone();
            Calendar toCalendar = dtfmt.getCalendar().clone();
            fromCalendar.setTimeInMillis(dtitv.getFromDate());
            toCalendar.setTimeInMillis(dtitv.getToDate());
            dtitvfmt.format(fromCalendar, toCalendar, str, pos);

            String expected = data[i++];
            String formatted = dtitvfmt.format(dtitv).toString();
            if (!formatted.equals(Utility.unescape(expected))) {
                errln(
                        "CLDR: \""
                                + locName
                                + "\\"
                                + datestr
                                + "\\"
                                + datestr_2
                                + "\"\t expected: "
                                + expected
                                + "\tgot: "
                                + formatted
                                + "\n");
            }
        }
    }

    /** Stress test */
    @Test
    public void TestStress() {
        if (TestFmwk.getExhaustiveness() <= 5) {
            logln("INFO: Skipping test");
            return;
        }

        // test data.
        // The 1st is the format pattern,
        // Next are pairs in which the 1st in the pair is the earlier date
        // and the 2nd in the pair is the later date
        String[] DATA = {
            "yyyy MM dd HH:mm:ss",
            "2007 10 10 10:10:10",
            "2008 10 10 10:10:10",
            "2007 10 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 11 10 10:10:10",
            "2007 11 20 10:10:10",
            "2007 01 10 10:00:10",
            "2007 01 10 14:10:10",
            "2007 01 10 10:00:10",
            "2007 01 10 10:20:10",
            "2007 01 10 10:10:10",
            "2007 01 10 10:10:20",
        };

        String[][] testLocale = {
            {"en", "", ""},
            {"zh", "", ""},
            {"de", "", ""},
            {"ar", "", ""},
            {"en", "GB", ""},
            {"fr", "", ""},
            {"it", "", ""},
            {"nl", "", ""},
            {"zh", "TW", ""},
            {"ja", "", ""},
            {"pt", "BR", ""},
            {"ru", "", ""},
            {"tr", "", ""},
            {"es", "", ""},
            {"ko", "", ""},
            // {"th", "", ""},
            {"sv", "", ""},
            {"pl", "", ""},
            {"fi", "", ""},
            {"da", "", ""},
            {"pt", "PT", ""},
            {"ro", "", ""},
            {"hu", "", ""},
            {"he", "", ""},
            {"in", "", ""},
            {"cs", "", ""},
            {"el", "", ""},
            {"no", "", ""},
            {"vi", "", ""},
            {"bg", "", ""},
            {"hr", "", ""},
            {"lt", "", ""},
            {"sk", "", ""},
            {"sl", "", ""},
            {"sr", "", ""},
            {"ca", "", ""},
            {"lv", "", ""},
            {"uk", "", ""},
            {"hi", "", ""},
        };

        int localeIndex;
        for (localeIndex = 0; localeIndex < testLocale.length; ++localeIndex) {
            stress(
                    DATA,
                    DATA.length,
                    new Locale(
                            testLocale[localeIndex][0],
                            testLocale[localeIndex][1],
                            testLocale[localeIndex][2]),
                    testLocale[localeIndex][0] + testLocale[localeIndex][1]);
        }
    }

    private void stress(String[] data, int data_length, Locale loc, String locName) {
        String[] skeleton = {
            "EEEEdMMMMy",
            "dMMMMy",
            "dMMMM",
            "MMMMy",
            "EEEEdMMMM",
            "EEEdMMMy",
            "dMMMy",
            "dMMM",
            "MMMy",
            "EEEdMMM",
            "EEEdMy",
            "dMy",
            "dM",
            "My",
            "EEEdM",
            "d",
            "EEEd",
            "y",
            "M",
            "MMM",
            "MMMM",
            "hm",
            "hmv",
            "hmz",
            "h",
            "hv",
            "hz",
            "EEddMMyyyy", // following could be normalized
            "EddMMy",
            "hhmm",
            "hhmmzz",
            "hms", // following could not be normalized
            "dMMMMMy",
            "EEEEEdM",
        };

        int i = 0;

        SimpleDateFormat ref = new SimpleDateFormat(data[i++], loc);

        while (i < data_length) {
            // 'f'
            String datestr = data[i++];
            String datestr_2 = data[i++];
            Date date;
            Date date_2;
            try {
                date = ref.parse(datestr);
                date_2 = ref.parse(datestr_2);
            } catch (ParseException e) {
                errln("parse exception" + e);
                continue;
            }
            DateInterval dtitv = new DateInterval(date.getTime(), date_2.getTime());

            for (int skeletonIndex = 0; skeletonIndex < skeleton.length; ++skeletonIndex) {
                String oneSkeleton = skeleton[skeletonIndex];
                // need special handle of "Thai" since the default calendar
                // of "Thai" is "Budd", not "Gregorian".
                DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(oneSkeleton, loc);
                /*
                if ( locName.equals("th") ) {
                    // reset calendar to be Gregorian
                    GregorianCalendar gregCal = new GregorianCalendar(loc);
                    DateFormat dformat = dtitvfmt.getDateFormat();
                    DateFormat newOne = (DateFormat)dformat.clone();
                    newOne.setCalendar(gregCal);
                    dtitvfmt.setDateFormat(newOne);
                }
                 */
                dtitvfmt.format(dtitv);
            }

            // test interval format by algorithm
            for (int style = DateFormat.FULL; style < 4; ++style) {
                SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateInstance(style, loc);
                FieldPosition pos = new FieldPosition(0);
                StringBuffer str = new StringBuffer("");
                Calendar fromCalendar = dtfmt.getCalendar().clone();
                Calendar toCalendar = dtfmt.getCalendar().clone();
                fromCalendar.setTimeInMillis(dtitv.getFromDate());
                toCalendar.setTimeInMillis(dtitv.getToDate());
                dtfmt.intervalFormatByAlgorithm(fromCalendar, toCalendar, str, pos);
            }
        }
    }

    /*
     * Ticket#6396 DateIntervalInfo of ICU4J 4.0d3 throw NullPointerException
     */
    @Test
    public void TestT6396() {
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("th_TH"));
        try {
            // ticket#6396 reported toString() throws NullPointerException
            String diiStr = dii.toString();
            logln("new DateIntervalInfo(new ULocale(\"th_TH\")).toString() - " + diiStr);

            // equals also had the similar problem
            DateIntervalInfo dii1 = dii.clone();
            if (!dii.equals(dii1)) {
                errln("FAIL: Cloned DateIntervalInfo is not equal to the source");
            }
        } catch (Exception e) {
            errln("FAIL: Exception - " + e.getClass().getName());
        }
    }

    @Test
    public void TestConstructor() {
        DateIntervalInfo diiJapan = new DateIntervalInfo(ULocale.JAPAN);
        DateIntervalInfo diiJapanJ = new DateIntervalInfo(Locale.JAPAN);

        assertEquals("DateIntervalInfo constructors", diiJapan, diiJapanJ);
    }

    /* Tests the method
     *      public boolean equals(Object a)
     */
    @Test
    public void TestDateIntervalInfoEquals() {
        // Tests when "if ( a instanceof PatternInfo )" is false
        DateIntervalInfo diia = new DateIntervalInfo();
        if (diia.equals("dummy")) {
            errln(
                    "DateIntervalInfo.equals(Object a) was suppose to return "
                            + "false for a String object.");
        }
        if (diia.equals(0)) {
            errln(
                    "DateIntervalInfo.equals(Object a) was suppose to return "
                            + "false for an Integer object.");
        }
        if (diia.equals(0.0)) {
            errln(
                    "DateIntervalInfo.equals(Object a) was suppose to return "
                            + "false for an Integer object.");
        }
        if (diia.equals(new Object())) {
            errln(
                    "DateIntervalInfo.equals(Object a) was suppose to return "
                            + "false for an Integer object.");
        }
    }

    /* Tests the method
     *      public Object cloneAsThawed()
     */
    @Test
    public void TestCloseAsThawed() {
        DateIntervalInfo dii = new DateIntervalInfo();
        try {
            dii.cloneAsThawed();
        } catch (Exception e) {
            errln("DateIntervalInfo.closeAsThawed() was not suppose to return " + "an exception.");
        }
    }

    /* Tests the method
     *      public boolean isFrozen()
     */
    @Test
    public void TestIsFrozen() {
        DateIntervalInfo dii = new DateIntervalInfo();
        if (dii.isFrozen() != false) {
            errln("DateIntervalInfo.isFrozen() is suppose to return false.");
        }
        dii.freeze();

        if (dii.isFrozen() != true) {
            errln("DateIntervalInfo.isFrozen() is suppose to return true.");
        }
    }

    /* Tests the method
     *      public boolean clone()
     */
    @Test
    public void TestClone() {
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("en_US"));
        DateIntervalInfo dii_clone = dii.clone();
        dii_clone.freeze();

        // Tests when "if ( frozen )" is true
        if (!dii.equals(dii_clone)) {
            errln(
                    "DateIntervalInfo.clone() is suppose to return true for "
                            + "an original DateIntervalInfo object and a clone of the "
                            + "original DateIntervalInfo object.");
        }
    }

    /* Tests the method
     *      public void setFallbackIntervalPattern(String fallbackPattern)
     */
    @Test
    public void TestSetFallbackIntervalPattern() {
        DateIntervalInfo dii = new DateIntervalInfo(new ULocale("en_US"));
        // Tests when "if ( frozen )" is true
        try {
            dii.freeze();
            dii.setFallbackIntervalPattern("");
            errln(
                    "DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) "
                            + "was suppose to return an exception for a frozen object.");
        } catch (Exception e) {
        }

        // Tests when "if ( firstPatternIndex == -1 || secondPatternIndex == -1 )" is true
        dii = dii.cloneAsThawed();
        try {
            dii.setFallbackIntervalPattern("");
            errln(
                    "DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) "
                            + "was suppose to return an exception for a string object of ''.");
        } catch (Exception e) {
        }

        try {
            dii.setFallbackIntervalPattern("0");
            errln(
                    "DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) "
                            + "was suppose to return an exception for a string object of 0.");
        } catch (Exception e) {
        }

        // Tests when "if ( firstPatternIndex > secondPatternIndex )" is true
        dii.setFallbackIntervalPattern("{1}{0}");
        if (dii.getDefaultOrder() != true)
            errln(
                    "DateIntervalInfo.setFallbackIntervalPattern(String fallbackPattern) "
                            + "was suppose to change the variable 'fFirstDateInPtnIsLaterDate' "
                            + "to true.");
    }

    /* Tests the method
     *      public PatternInfo getIntervalPattern(String skeleton, int field)
     */
    @Test
    public void TestGetIntervalPattern() {
        // Tests when "if ( field > MINIMUM_SUPPORTED_CALENDAR_FIELD )" is true
        // MINIMUM_SUPPORTED_CALENDAR_FIELD = Calendar.MILLISECOND;
        DateIntervalInfo dii = new DateIntervalInfo();
        try {
            dii.getIntervalPattern("", Calendar.MILLISECOND + 1);
            errln(
                    "DateIntervalInfo.getIntervalPattern(String,int) was suppose "
                            + "to return an exception for the 'int field' parameter "
                            + "when it exceeds MINIMUM_SUPPORTED_CALENDAR_FIELD.");
        } catch (Exception e) {
        }
    }

    /* Tests the method
     *      public void setIntervalPattern(String skeleton, int lrgDiffCalUnit, String intervalPattern)
     */
    @Test
    public void TestSetIntervalPattern() {
        DateIntervalInfo dii = new DateIntervalInfo();
        // Tests when "if ( frozen )" is true
        try {
            dii.freeze();
            dii.setIntervalPattern("", 0, "");
            errln(
                    "DateIntervalInfo.setIntervalPattern(String,int,String) "
                            + "was suppose to return an exception when the "
                            + "DateIntervalInfo object is frozen.");
        } catch (Exception e) {
        }

        // Tests when "if ( lrgDiffCalUnit > MINIMUM_SUPPORTED_CALENDAR_FIELD )" is true
        // MINIMUM_SUPPORTED_CALENDAR_FIELD = Calendar.MILLISECOND;
        try {
            dii = dii.cloneAsThawed();
            dii.setIntervalPattern("", Calendar.MILLISECOND + 1, "");
            errln(
                    "DateIntervalInfo.setIntervalPattern(String,int,String) "
                            + "was suppose to return an exception when the "
                            + "variable 'lrgDiffCalUnit' is greater than "
                            + "MINIMUM_SUPPORTED_CALENDAR_FIELD.");
        } catch (Exception e) {
        }
    }

    @Test
    public void TestSetIntervalPatternNoSideEffect() {
        PatternInfo patternInfo =
                new DateIntervalInfo(ULocale.ENGLISH).getIntervalPattern("yMd", Calendar.DATE);
        String expectedPattern = patternInfo.getFirstPart() + patternInfo.getSecondPart();
        new DateIntervalInfo(ULocale.ENGLISH)
                .setIntervalPattern("yMd", Calendar.DATE, "M/d/y \u2013 d");
        patternInfo =
                new DateIntervalInfo(ULocale.ENGLISH).getIntervalPattern("yMd", Calendar.DATE);
        String actualPattern = patternInfo.getFirstPart() + patternInfo.getSecondPart();
        assertEquals(
                "setIntervalPattern should not have side effects", expectedPattern, actualPattern);
    }

    @Test
    public void TestGetSetTimeZone() {
        DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("MMMdHHmm", Locale.ENGLISH);
        long date1 =
                1299090600000L; // 2011-Mar-02 1030 in US/Pacific, 2011-Mar-03 0330 in Asia/Tokyo
        long date2 =
                1299115800000L; // 2011-Mar-02 1730 in US/Pacific, 2011-Mar-03 1030 in Asia/Tokyo
        DateInterval dtitv = new DateInterval(date1, date2);
        TimeZone tzCalif = TimeZone.getFrozenTimeZone("US/Pacific");
        TimeZone tzTokyo = TimeZone.getFrozenTimeZone("Asia/Tokyo");
        String fmtCalif =
                "Mar 2, 10:30\u2009\u2013\u200917:30"; // ICU4C result is "Mar 2, 10:30 \u2013
        // 17:30" (does not duplicate day)
        String fmtTokyo =
                "Mar 3, 03:30\u2009\u2013\u200910:30"; // ICU4C result is "Mar 3, 03:30 \u2013
        // 10:30" (does not duplicate day)

        StringBuffer buf = new StringBuffer();
        FieldPosition pos = new FieldPosition(0);
        dtitvfmt.setTimeZone(tzCalif);
        dtitvfmt.format(dtitv, buf, pos);
        if (!buf.toString().equals(fmtCalif)) {
            errln(
                    "DateIntervalFormat for tzCalif, expect \""
                            + fmtCalif
                            + "\", get \""
                            + buf
                            + "\"");
        }

        buf.setLength(0);
        pos.setBeginIndex(0);
        dtitvfmt.setTimeZone(tzTokyo);
        dtitvfmt.format(dtitv, buf, pos);
        if (!buf.toString().equals(fmtTokyo)) {
            errln(
                    "DateIntervalFormat for tzTokyo, expect \""
                            + fmtTokyo
                            + "\", get \""
                            + buf
                            + "\"");
        }

        if (!dtitvfmt.getTimeZone().equals(tzTokyo)) {
            errln("DateIntervalFormat.getTimeZone() returns mismatch");
        }
    }

    /* Tests the method
     *      public int hashCode()
     */
    @Test
    public void TestHashCode() {
        // Tests when
        //      "int hash = fIntervalPatternFirstPart != null ? fIntervalPatternFirstPart.hashCode()
        // : 0;"
        // is false
        PatternInfo dp = new PatternInfo(null, null, false);
        if (dp.hashCode() != 0) {
            errln(
                    "PatternInfo.hashCode() was suppose to return 0 for a null "
                            + "parameter in the constructor.");
        }
    }

    /* Tests the method
     *      public boolean equals(Object a)
     * in PatternInfo
     */
    @Test
    public void TestPattternInfoEquals() {
        // Tests when "if ( a instanceof PatternInfo )" is false
        PatternInfo pi = new PatternInfo("", "", false);
        if (pi.equals(new Object())) {
            errln(
                    "PatternInfo.equals(Object) is suppose to return false "
                            + "when it is not an instance of PatternInfo.");
        }
        if (pi.equals("")) {
            errln(
                    "PatternInfo.equals(Object) is suppose to return false "
                            + "when it is not an instance of PatternInfo.");
        }
        if (pi.equals(0)) {
            errln(
                    "PatternInfo.equals(Object) is suppose to return false "
                            + "when it is not an instance of PatternInfo.");
        }
        if (pi.equals(0.0)) {
            errln(
                    "PatternInfo.equals(Object) is suppose to return false "
                            + "when it is not an instance of PatternInfo.");
        }
    }

    @Test
    public void TestDateIntervalCoverage() {
        DateInterval di = new DateInterval(0, 1);

        if (di.equals("Test")) {
            errln("Comparison test should fail.");
        }

        if (di.toString() == null) {
            errln("toString should not return null.");
        }

        if (di.hashCode() != 1) {
            errln("hasCode() should return 1.");
        }
    }

    @Test
    public void testGetInstance_String_DateIntervalInfo() {
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(new ULocale("ca"));
        DateIntervalFormat dateIntervalFormat =
                DateIntervalFormat.getInstance(
                        DateFormat.YEAR_MONTH, Locale.ENGLISH, dateIntervalInfo);
        Calendar from = Calendar.getInstance();
        from.set(2000, Calendar.JANUARY, 1, 12, 0);
        Calendar to = Calendar.getInstance();
        to.set(2001, Calendar.FEBRUARY, 1, 12, 0);
        DateInterval interval = new DateInterval(from.getTimeInMillis(), to.getTimeInMillis());
        dateIntervalFormat.setTimeZone(from.getTimeZone());
        // Month names are default (English), format is Catalan
        assertEquals(
                "Wrong date interval",
                "January del 2000\u2009–\u2009February del 2001",
                dateIntervalFormat.format(interval));
    }

    @Test
    public void testGetInstance_String_Locale_DateIntervalInfo() {
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(new ULocale("ca"));
        DateIntervalFormat dateIntervalFormat =
                DateIntervalFormat.getInstance(
                        DateFormat.YEAR_MONTH, Locale.GERMAN, dateIntervalInfo);
        Calendar from = Calendar.getInstance();
        from.set(2000, Calendar.JANUARY, 1, 12, 0);
        Calendar to = Calendar.getInstance();
        to.set(2001, Calendar.FEBRUARY, 1, 12, 0);
        DateInterval interval = new DateInterval(from.getTimeInMillis(), to.getTimeInMillis());
        dateIntervalFormat.setTimeZone(from.getTimeZone());
        // Month names are German, format is Catalan
        assertEquals(
                "Wrong date interval",
                "Januar del 2000\u2009–\u2009Februar del 2001",
                dateIntervalFormat.format(interval));
    }

    @Test(expected = UnsupportedOperationException.class)
    public void testParseObject_notSupported() throws ParseException {
        DateIntervalFormat.getInstance(DateFormat.YEAR_MONTH).parseObject("");
    }

    @Test
    public void TestDateIntervalFormatCoverage() throws Exception {
        long date1 = 1299090600000L;
        long date2 = 1299115800000L;
        DateInterval dtitv = new DateInterval(date1, date2);
        DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance("MMMd", Locale.ENGLISH);
        DateIntervalInfo dtintinf = new DateIntervalInfo(ULocale.ENGLISH);

        // Check the default private constructor
        checkDefaultPrivateConstructor(DateIntervalFormat.class);

        // Check clone
        DateIntervalFormat dtitvfmtClone = dtitvfmt.clone();
        assertEquals(
                "DateIntervalFormat.clone() failed",
                dtitvfmt.format(dtitv),
                dtitvfmtClone.format(dtitv));

        // Coverage for getInstance
        assertNotNull(
                "Expected DateIntervalFormat object",
                DateIntervalFormat.getInstance("MMMd", dtintinf));
        assertNotNull(
                "Expected DateIntervalFormat object",
                DateIntervalFormat.getInstance("MMMdHHmm", Locale.ENGLISH, dtintinf));

        // Coverage for parseObject. Exception expected.
        try {
            dtitvfmt.parseObject("", new ParsePosition(0));
            errln("Exception was expected when calling DateIntervalFormat.parseObject()");
        } catch (Exception e) {
            /* No op */
        }

        // Check getPatterns()
        Output<String> secondPart = new Output<>();
        Calendar fromCalendar = Calendar.getInstance(Locale.ENGLISH);
        fromCalendar.set(2016, 5, 22);
        Calendar toCalendar = Calendar.getInstance(Locale.ENGLISH);
        toCalendar.set(2016, 5, 23);
        assertEquals(
                "Date interval pattern mismatch.",
                dtitvfmt.getPatterns(fromCalendar, toCalendar, secondPart),
                "MMM d\u2009–\u2009");
        assertEquals("Date interval pattern mismatch.", secondPart.value, "d");
    }

    @Test
    public void TestTicket9919GetInstance() {
        // Creating a DateIntervalFormat with a custom DateIntervalInfo
        // object used to corrupt the cache.
        DateIntervalFormat dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(2013, 3, 26);
        to.set(2013, 3, 28);

        // Save. This is the correct answer
        String expected = dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString();

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with a custom DateIntervalInfo. This used
        // to corrupt the cache.
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(ULocale.ENGLISH);
        dateIntervalInfo.setIntervalPattern("yMd", Calendar.DATE, "M/d/y \u2013 d");
        DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH, dateIntervalInfo);

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with default DateIntervalInfo. The cache should
        // not be corrupted, and we should get the same answer as before.
        dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);

        assertEquals(
                "Custom DateIntervalInfo objects should not mess up cache",
                expected,
                dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString());
    }

    @Test
    public void TestTicket9919Setter() {

        // Creating a DateIntervalFormat with a custom DateIntervalInfo
        // object used to corrupt the cache.
        DateIntervalFormat dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);
        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(2013, 3, 26);
        to.set(2013, 3, 28);

        // Save. This is the correct answer
        String expected = dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString();

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with a custom DateIntervalInfo. This used
        // to corrupt the cache.
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(ULocale.ENGLISH);
        dateIntervalInfo.setIntervalPattern("yMd", Calendar.DATE, "M/d/y \u2013 d");
        DateIntervalFormat bad = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);
        bad.setDateIntervalInfo(dateIntervalInfo);

        // Now create a DateIntervalFormat with same skeleton and
        // locale, but with default DateIntervalInfo. The cache should
        // not be corrupted, and we should get the same answer as before.
        dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH);
        assertEquals(
                "Custom DateIntervalInfo objects should not mess up cache",
                expected,
                dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString());
    }

    @Test
    public void TestTicket9914() {
        DateIntervalInfo dateIntervalInfo = new DateIntervalInfo(ULocale.ENGLISH);

        Calendar from = Calendar.getInstance();
        Calendar to = Calendar.getInstance();
        from.set(113, 3, 26);
        to.set(113, 3, 28);
        DateIntervalFormat dif =
                DateIntervalFormat.getInstance("yyyyMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yyyyMd skeleton.",
                "4/26/0113\u2009\u2013\u20094/28/0113",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString());

        dif = DateIntervalFormat.getInstance("yyMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yyMd skeleton.",
                "4/26/13\u2009\u2013\u20094/28/13",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString());

        dif = DateIntervalFormat.getInstance("yMd", ULocale.ENGLISH, dateIntervalInfo);
        assertEquals(
                "yMd skeleton.",
                "4/26/113\u2009\u2013\u20094/28/113",
                dif.format(from, to, new StringBuffer(), new FieldPosition(0)).toString());
    }

    @Test
    public void TestTicket11583() {
        ULocale[] locales = {
            ULocale.ENGLISH, SPANISH, LA_SPANISH,
        };
        String[] skeletons = {
            "yMMMMd", "yMMMM", "MMMM", "yMMMd", "yMMM", "MMM", "yMMd", "yMMdd", "yMM", "MM", "yMdd",
            "yMd", "yM", "M"
        };

        final long startDate = 1232364615000L;
        final long endDate = 1240399815000L;
        String filterPattern = null; // "yMMM";

        for (ULocale locale : locales) {
            for (String skeleton : skeletons) {
                if (filterPattern != null && !skeleton.equals(filterPattern)) {
                    continue;
                }

                DateFormat dateFormat = DateFormat.getPatternInstance(skeleton, locale);
                String dateFormatPattern = ((SimpleDateFormat) dateFormat).toPattern();

                DateIntervalFormat intervalFormat =
                        DateIntervalFormat.getInstance(skeleton, locale);
                DateIntervalInfo intervalInfo = intervalFormat.getDateIntervalInfo();

                if (skeleton.equals(filterPattern)) {
                    logln(
                            filterPattern
                                    + " => "
                                    + intervalInfo.getRawPatterns().get(filterPattern));
                }

                DateInterval date_interval = new DateInterval(startDate, endDate);

                String interval = intervalFormat.format(date_interval);

                String formattedStart = dateFormat.format(startDate);
                String formattedEnd = dateFormat.format(endDate);

                PatternInfo patternInfo = intervalFormat.getRawPatterns().get("M");

                String firstPart = patternInfo.getFirstPart();
                String secondPart = patternInfo.getSecondPart();
                if (!matches(dateFormatPattern, firstPart, secondPart)) {
                    if (logKnownIssue(
                            "ICU-11585",
                            "incompatible pattern between date format and date interval format")) {
                        logln(
                                "For skeleton "
                                        + skeleton
                                        + "/locale "
                                        + locale
                                        + ": mismatch between date format «"
                                        + dateFormatPattern
                                        + "» and date interval format «"
                                        + firstPart
                                        + secondPart
                                        + "».");
                    } else {
                        errln(
                                "For skeleton "
                                        + skeleton
                                        + "/locale "
                                        + locale
                                        + ": mismatch between date format «"
                                        + dateFormatPattern
                                        + "» and date interval format «"
                                        + firstPart
                                        + secondPart
                                        + "».");
                    }
                }

                logln(
                        locale
                                + "\tskeleton: «"
                                + skeleton
                                + "»\tpattern: «"
                                + dateFormatPattern
                                + "»\tintervalPattern1: «"
                                + firstPart
                                + "»\tintervalPattern2: «"
                                + secondPart
                                + "»\tstartDate: «"
                                + formattedStart
                                + "»\tendDate: «"
                                + formattedEnd
                                + "»\tinterval: «"
                                + interval
                                + "»");
            }
        }
    }

    /**
     * Return true if for some x, y: dateFormatPattern = firstPart(0,x) + secondPart(y,
     * secondPart.length())
     *
     * @param dateFormatPattern
     * @param firstPart
     * @param secondPart
     * @return
     */
    private boolean matches(String dateFormatPattern, String firstPart, String secondPart) {
        // brute force for now
        int lastButOne = dateFormatPattern.length() - 1;
        for (int i = 1; i < lastButOne; ++i) {
            if (firstPart.startsWith(dateFormatPattern.substring(0, i))
                    && secondPart.endsWith(
                            dateFormatPattern.substring(i, dateFormatPattern.length()))) {
                return true;
            }
        }
        return false;
    }

    @Test
    public void TestFPos_SkelWithSeconds() {

        final long[] deltas = {
            0L, // none
            200L, // 200 millisec
            20000L, // 20 sec
            1200000L, // 20 min
            7200000L, // 2 hrs
            43200000L, // 12 hrs
            691200000L, // 8 days
            1382400000L, // 16 days,
            8640000000L, // 100 days
        };

        class ExpectPosAndFormat {
            public int posBegin;
            public int posEnd;
            public String format;

            // Simple constructor
            public ExpectPosAndFormat(int pBegin, int pEnd, String fmt) {
                posBegin = pBegin;
                posEnd = pEnd;
                format = fmt;
            }
        }
        ;

        final ExpectPosAndFormat[] exp_en_HHmm = {
            new ExpectPosAndFormat(3, 5, "09:00"),
            new ExpectPosAndFormat(3, 5, "09:00"),
            new ExpectPosAndFormat(3, 5, "09:00"),
            new ExpectPosAndFormat(3, 5, "09:00\u2009\u2013\u200909:20"),
            new ExpectPosAndFormat(3, 5, "09:00\u2009\u2013\u200911:00"),
            new ExpectPosAndFormat(3, 5, "09:00\u2009\u2013\u200921:00"),
            new ExpectPosAndFormat(15, 17, "11/20/2014, 09:00\u2009\u2013\u200911/28/2014, 09:00"),
            new ExpectPosAndFormat(15, 17, "11/20/2014, 09:00\u2009\u2013\u200912/6/2014, 09:00"),
            new ExpectPosAndFormat(15, 17, "11/20/2014, 09:00\u2009\u2013\u20092/28/2015, 09:00")
        };

        final ExpectPosAndFormat[] exp_en_HHmmss = {
            new ExpectPosAndFormat(3, 5, "09:00:00"),
            new ExpectPosAndFormat(3, 5, "09:00:00"),
            new ExpectPosAndFormat(3, 5, "09:00:00\u2009\u2013\u200909:00:20"),
            new ExpectPosAndFormat(3, 5, "09:00:00\u2009\u2013\u200909:20:00"),
            new ExpectPosAndFormat(3, 5, "09:00:00\u2009\u2013\u200911:00:00"),
            new ExpectPosAndFormat(3, 5, "09:00:00\u2009\u2013\u200921:00:00"),
            new ExpectPosAndFormat(
                    15, 17, "11/20/2014, 09:00:00\u2009\u2013\u200911/28/2014, 09:00:00"),
            new ExpectPosAndFormat(
                    15, 17, "11/20/2014, 09:00:00\u2009\u2013\u200912/6/2014, 09:00:00"),
            new ExpectPosAndFormat(
                    15, 17, "11/20/2014, 09:00:00\u2009\u2013\u20092/28/2015, 09:00:00")
        };

        final ExpectPosAndFormat[] exp_en_yyMMdd = {
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14\u2009\u2013\u200911/28/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14\u2009\u2013\u200912/6/14"),
            new ExpectPosAndFormat(0, 0, "11/20/14\u2009\u2013\u20092/28/15")
        };

        final ExpectPosAndFormat[] exp_en_yyMMddHHmm = {
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200909:20"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200911:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200921:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200911/28/14, 09:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200912/06/14, 09:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00\u2009\u2013\u200902/28/15, 09:00")
        };

        final ExpectPosAndFormat[] exp_en_yyMMddHHmmss = {
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00\u2009\u2013\u200909:00:20"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00\u2009\u2013\u200909:20:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00\u2009\u2013\u200911:00:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00\u2009\u2013\u200921:00:00"),
            new ExpectPosAndFormat(
                    13, 15, "11/20/14, 09:00:00\u2009\u2013\u200911/28/14, 09:00:00"),
            new ExpectPosAndFormat(
                    13, 15, "11/20/14, 09:00:00\u2009\u2013\u200912/06/14, 09:00:00"),
            new ExpectPosAndFormat(13, 15, "11/20/14, 09:00:00\u2009\u2013\u200902/28/15, 09:00:00")
        };

        @SuppressWarnings("unused")
        final ExpectPosAndFormat[] exp_en_yMMMdhmmssz = {
            new ExpectPosAndFormat(16, 18, "Nov 20, 2014, 9:00:00\u202FAM GMT"),
            new ExpectPosAndFormat(16, 18, "Nov 20, 2014, 9:00:00\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u20099:00:20\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u20099:20:00\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u200911:00:00\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u20099:00:00\u202FPM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u2009Nov 28, 2014, 9:00:00\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u2009Dec 6, 2014, 9:00:00\u202FAM GMT"),
            new ExpectPosAndFormat(
                    16,
                    18,
                    "Nov 20, 2014, 9:00:00\u202FAM GMT\u2009\u2013\u2009Feb 28, 2015, 9:00:00\u202FAM GMT")
        };

        final ExpectPosAndFormat[] exp_ja_yyMMddHHmm = {
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9\u664200\u5206\uFF5E9\u664220\u5206"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9\u664200\u5206\uFF5E11\u664200\u5206"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9\u664200\u5206\uFF5E21\u664200\u5206"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00\uFF5E14/11/28 9:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00\uFF5E14/12/06 9:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00\uFF5E15/02/28 9:00")
        };

        final ExpectPosAndFormat[] exp_ja_yyMMddHHmmss = {
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E9:00:20"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E9:20:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E11:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E21:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E14/11/28 9:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E14/12/06 9:00:00"),
            new ExpectPosAndFormat(11, 13, "14/11/20 9:00:00\uFF5E15/02/28 9:00:00")
        };

        final ExpectPosAndFormat[] exp_ja_yMMMdHHmmss = {
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00"),
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00"),
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E9:00:20"),
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E9:20:00"),
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E11:00:00"),
            new ExpectPosAndFormat(14, 16, "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E21:00:00"),
            new ExpectPosAndFormat(
                    14,
                    16,
                    "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2014\u5E7411\u670828\u65E5 9:00:00"),
            new ExpectPosAndFormat(
                    14,
                    16,
                    "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2014\u5E7412\u67086\u65E5 9:00:00"),
            new ExpectPosAndFormat(
                    14,
                    16,
                    "2014\u5E7411\u670820\u65E5 9:00:00\uFF5E2015\u5E742\u670828\u65E5 9:00:00")
        };

        class LocaleAndSkeletonItem {
            public String locale;
            public String skeleton;
            public int fieldToCheck;
            public ExpectPosAndFormat[] expected;

            // Simple constructor
            public LocaleAndSkeletonItem(
                    String loc, String skel, int field, ExpectPosAndFormat[] exp) {
                locale = loc;
                skeleton = skel;
                fieldToCheck = field;
                expected = exp;
            }
        }
        ;

        final LocaleAndSkeletonItem[] locSkelItems = {
            new LocaleAndSkeletonItem("en", "HHmm", DateFormat.MINUTE_FIELD, exp_en_HHmm),
            new LocaleAndSkeletonItem("en", "HHmmss", DateFormat.MINUTE_FIELD, exp_en_HHmmss),
            new LocaleAndSkeletonItem("en", "yyMMdd", DateFormat.MINUTE_FIELD, exp_en_yyMMdd),
            new LocaleAndSkeletonItem(
                    "en", "yyMMddHHmm", DateFormat.MINUTE_FIELD, exp_en_yyMMddHHmm),
            new LocaleAndSkeletonItem(
                    "en", "yyMMddHHmmss", DateFormat.MINUTE_FIELD, exp_en_yyMMddHHmmss),
            // skip the following until ICU4J DateIntervalFormat has support for setting time zone
            // new LocaleAndSkeletonItem( "en",		"yMMMdhmmssz",  DateFormat.MINUTE_FIELD,
            // exp_en_yMMMdhmmssz ),
            new LocaleAndSkeletonItem(
                    "ja", "yyMMddHHmm", DateFormat.MINUTE_FIELD, exp_ja_yyMMddHHmm),
            new LocaleAndSkeletonItem(
                    "ja", "yyMMddHHmmss", DateFormat.MINUTE_FIELD, exp_ja_yyMMddHHmmss),
            new LocaleAndSkeletonItem(
                    "ja", "yMMMdHHmmss", DateFormat.MINUTE_FIELD, exp_ja_yMMMdHHmmss)
        };

        // final String zoneGMT = "GMT";
        final long startTimeGMT = 1416474000000L; // 2014 Nov 20 09:00 GMT

        TimeZone localZone = TimeZone.getDefault();
        long startTime = startTimeGMT - localZone.getOffset(startTimeGMT);
        for (LocaleAndSkeletonItem item : locSkelItems) {
            DateIntervalFormat difmt =
                    DateIntervalFormat.getInstance(item.skeleton, new ULocale(item.locale));
            int dIdx, dCount = deltas.length;
            for (dIdx = 0; dIdx < dCount; dIdx++) {
                DateInterval di = new DateInterval(startTime, startTime + deltas[dIdx]);
                StringBuffer actual = new StringBuffer(64);
                FieldPosition pos = new FieldPosition(item.fieldToCheck);
                String actualString = difmt.format(di, actual, pos).toString();
                ExpectPosAndFormat expectPosFmt = item.expected[dIdx];
                if (!actualString.equals(expectPosFmt.format)
                        || pos.getBeginIndex() != expectPosFmt.posBegin
                        || pos.getEndIndex() != expectPosFmt.posEnd) {
                    errln(
                            "For locale "
                                    + item.locale
                                    + ", skeleton "
                                    + item.skeleton
                                    + ", delta "
                                    + deltas[dIdx]
                                    + ": expect "
                                    + expectPosFmt.posBegin
                                    + "-"
                                    + expectPosFmt.posEnd
                                    + " \""
                                    + expectPosFmt.format
                                    + "\"; get "
                                    + pos.getBeginIndex()
                                    + "-"
                                    + pos.getEndIndex()
                                    + " \""
                                    + actualString
                                    + "\"");
                }
            }
        }
    }

    // TestTicket11669 - Check the thread safety of DateIntervalFormat.format().
    //                   This test failed with ICU 56.
    @Test
    public void TestTicket11669() {
        // These final variables are accessed directly by the concurrent threads.
        final DateIntervalFormat formatter =
                DateIntervalFormat.getInstance(DateFormat.YEAR_MONTH_DAY, ULocale.US);
        final ArrayList<DateInterval> testIntervals = new ArrayList<>();
        final ArrayList<String> expectedResults = new ArrayList<>();

        // Create and save the input test data.
        TimeZone tz = TimeZone.getTimeZone("Americal/Los_Angeles");
        Calendar intervalStart = Calendar.getInstance(tz, ULocale.US);
        Calendar intervalEnd = Calendar.getInstance(tz, ULocale.US);
        intervalStart.set(2009, 6, 1);
        intervalEnd.set(2009, 6, 2);
        testIntervals.add(
                new DateInterval(intervalStart.getTimeInMillis(), intervalEnd.getTimeInMillis()));
        intervalStart.set(2015, 2, 27);
        intervalEnd.set(2015, 3, 1);
        testIntervals.add(
                new DateInterval(intervalStart.getTimeInMillis(), intervalEnd.getTimeInMillis()));

        // Run the formatter single-threaded to create and save the expected results.
        for (DateInterval interval : testIntervals) {
            FieldPosition pos = new FieldPosition(0);
            StringBuffer result = new StringBuffer();
            formatter.format(interval, result, pos);
            expectedResults.add(result.toString());
        }

        class TestThread extends Thread {
            public String errorMessage;

            @Override
            public void run() {
                for (int loop = 0; loop < 2000; ++loop) {
                    ListIterator<String> expectedItr = expectedResults.listIterator();
                    for (DateInterval interval : testIntervals) {
                        String expected = expectedItr.next();
                        FieldPosition pos = new FieldPosition(0);
                        StringBuffer result = new StringBuffer();
                        formatter.format(interval, result, pos);
                        if (!expected.equals(result.toString())) {
                            // Note: The ICU test framework doesn't support reporting failures from
                            // within a sub-thread.
                            //       Save the failure for the main thread to pick up later.
                            errorMessage =
                                    String.format(
                                            "Expected \"%s\", actual \"%s\"", expected, result);
                            return;
                        }
                    }
                }
            }
        }

        List<TestThread> threads = new ArrayList<>();
        for (int i = 0; i < 4; ++i) {
            threads.add(new TestThread());
        }
        for (Thread t : threads) {
            t.start();
        }
        for (TestThread t : threads) {
            try {
                t.join();
            } catch (InterruptedException e) {
                fail("Unexpected exception: " + e.toString());
            }
            if (t.errorMessage != null) {
                fail(t.errorMessage);
            }
        }
    }

    @Test
    public void testFormattedDateInterval() {
        DateIntervalFormat fmt = DateIntervalFormat.getInstance("dMMMMy", ULocale.US);

        {
            String message = "FormattedDateInterval test 1";
            String expectedString = "July 20\u2009\u2013\u200925, 2018";
            Calendar input1 = Calendar.getInstance(ULocale.UK);
            Calendar input2 = Calendar.getInstance(ULocale.UK);
            input1.set(2018, 6, 20);
            input2.set(2018, 6, 25);
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            Object[][] expectedFieldPositions =
                    new Object[][] {
                        // field, begin index, end index
                        {DateFormat.Field.MONTH, 0, 4},
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 5, 7, 0},
                        {DateFormat.Field.DAY_OF_MONTH, 5, 7},
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 10, 12, 1},
                        {DateFormat.Field.DAY_OF_MONTH, 10, 12},
                        {DateFormat.Field.YEAR, 14, 18}
                    };
            FormattedValueTest.checkFormattedValue(
                    message, result, expectedString, expectedFieldPositions);
        }

        // Test sample code
        {
            Calendar input1 = Calendar.getInstance(ULocale.UK);
            Calendar input2 = Calendar.getInstance(ULocale.UK);
            input1.set(2018, 6, 20);
            input2.set(2018, 7, 3);

            // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy
            // Let input1 be July 20, 2018 and input2 be August 3, 2018:
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            assertEquals(
                    "Expected output from format",
                    "July 20\u2009\u2013\u2009August 3, 2018",
                    result.toString());
            ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
            cfpos.constrainFieldAndValue(DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 0);
            if (result.nextPosition(cfpos)) {
                assertEquals("Expect start index", 0, cfpos.getStart());
                assertEquals("Expect end index", 7, cfpos.getLimit());
            } else {
                // No such span: can happen if input dates are equal.
            }
            assertFalse("No more than one occurrence of the field", result.nextPosition(cfpos));
        }

        fmt = DateIntervalFormat.getInstance("dMMMha", ULocale.US);

        {
            String message = "FormattedDateInterval test 2";
            String expectedString = "Feb 15, 11\u202FAM\u2009\u2013\u20093\u202FPM";
            Calendar input1 = Calendar.getInstance(ULocale.US);
            Calendar input2 = Calendar.getInstance(ULocale.US);
            input1.set(2019, 1, 15, 11, 0, 0);
            input2.set(2019, 1, 15, 15, 0, 0);
            FormattedDateInterval result = fmt.formatToValue(input1, input2);
            Object[][] expectedFieldPositions =
                    new Object[][] {
                        // field, begin index, end index
                        {DateFormat.Field.MONTH, 0, 3},
                        {DateFormat.Field.DAY_OF_MONTH, 4, 6},
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 8, 13, 0},
                        {DateFormat.Field.HOUR1, 8, 10},
                        {DateFormat.Field.AM_PM, 11, 13},
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 16, 20, 1},
                        {DateFormat.Field.HOUR1, 16, 17},
                        {DateFormat.Field.AM_PM, 18, 20}
                    };
            FormattedValueTest.checkFormattedValue(
                    message, result, expectedString, expectedFieldPositions);
        }

        // To test the fallback pattern behavior, make a custom DateIntervalInfo.
        DateIntervalInfo dtitvinf = new DateIntervalInfo();
        dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>");
        fmt = DateIntervalFormat.getInstance("dMMMMy", ULocale.US, dtitvinf);

        {
            String message = "FormattedDateInterval with fallback format test 1";
            String expectedString = "<< July 25, 2018 --- July 20, 2018 >>";
            Date input1 = new Date(2018 - 1900, 6, 20);
            Date input2 = new Date(2018 - 1900, 6, 25);
            DateInterval dtiv = new DateInterval(input1.getTime(), input2.getTime());
            FormattedDateInterval result = fmt.formatToValue(dtiv);
            Object[][] expectedFieldPositions =
                    new Object[][] {
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 3, 16, 1},
                        {DateFormat.Field.MONTH, 3, 7},
                        {DateFormat.Field.DAY_OF_MONTH, 8, 10},
                        {DateFormat.Field.YEAR, 12, 16},
                        {DateIntervalFormat.SpanField.DATE_INTERVAL_SPAN, 21, 34, 0},
                        {DateFormat.Field.MONTH, 21, 25},
                        {DateFormat.Field.DAY_OF_MONTH, 26, 28},
                        {DateFormat.Field.YEAR, 30, 34}
                    };
            FormattedValueTest.checkFormattedValue(
                    message, result, expectedString, expectedFieldPositions);
        }
    }

    @Test
    public void testCreateInstanceForAllLocales() {
        boolean quick = (getExhaustiveness() <= 5);
        int count = 0;
        for (ULocale locale :
                ULocale.getAvailableLocalesByType(ULocale.AvailableType.WITH_LEGACY_ALIASES)) {
            // Only test 1/5 of the locale in quick mode.
            if (quick && (count++ % 5 > 0)) continue;
            @SuppressWarnings("unused")
            DateIntervalFormat fmt = DateIntervalFormat.getInstance("dMMMMy", locale);
            for (String calendar : Calendar.getKeywordValuesForLocale("calendar", locale, false)) {
                // Only test 1/7 of case in quick mode.
                if (quick && (count++ % 7 > 0)) continue;
                ULocale l = locale.setKeywordValue("calendar", calendar);
                fmt = DateIntervalFormat.getInstance("dMMMMy", l);
            }
        }
    }

    @Test
    public void testTicket20707() {
        TimeZone tz = TimeZone.getTimeZone("UTC");
        Locale locales[] = {
            Locale.forLanguageTag("en-u-hc-h24"),
            Locale.forLanguageTag("en-u-hc-h23"),
            Locale.forLanguageTag("en-u-hc-h12"),
            Locale.forLanguageTag("en-u-hc-h11"),
            Locale.forLanguageTag("en"),
            Locale.forLanguageTag("en-u-hc-h25"),
            Locale.forLanguageTag("hi-IN-u-hc-h11")
        };

        // Clomuns: hh, HH, kk, KK, jj, JJs, CC
        String expected[][] = {
            // Hour-cycle: k
            {"12\u202FAM", "24", "24", "12\u202FAM", "24", "0 (hour: 24)", "12\u202FAM"},
            // Hour-cycle: H
            {"12\u202FAM", "00", "00", "12\u202FAM", "00", "0 (hour: 00)", "12\u202FAM"},
            // Hour-cycle: h
            {"12\u202FAM", "00", "00", "12\u202FAM", "12\u202FAM", "0 (hour: 12)", "12\u202FAM"},
            // Hour-cycle: K
            {"0\u202FAM", "00", "00", "0\u202FAM", "0\u202FAM", "0 (hour: 00)", "0\u202FAM"},
            {"12\u202FAM", "00", "00", "12\u202FAM", "12\u202FAM", "0 (hour: 12)", "12\u202FAM"},
            {"12\u202FAM", "00", "00", "12\u202FAM", "12\u202FAM", "0 (hour: 12)", "12\u202FAM"},
            {
                "0\u202Fam",
                "00",
                "00",
                "0\u202Fam",
                "0\u202Fam",
                "0 (\u0918\u0902\u091F\u093E: 00)",
                "\u0930\u093E\u0924 0"
            }
        };

        int i = 0;
        for (Locale locale : locales) {
            int j = 0;
            String skeletons[] = {"hh", "HH", "kk", "KK", "jj", "JJs", "CC"};
            for (String skeleton : skeletons) {
                DateIntervalFormat dateFormat = DateIntervalFormat.getInstance(skeleton, locale);
                Calendar calendar = Calendar.getInstance(tz);
                calendar.setTime(new Date(1563235200000L));
                StringBuffer resultBuffer =
                        dateFormat.format(
                                calendar, calendar, new StringBuffer(""), new FieldPosition(0));

                assertEquals(
                        "Formatted result for " + skeleton + " locale: " + locale.getDisplayName(),
                        expected[i][j++],
                        resultBuffer.toString());
            }
            i++;
        }
    }

    @Test
    public void testFormatMillisecond() {
        Object[][] kTestCases = {
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "ms",
                "23:45"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "msS",
                "23:45.3"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "msSS",
                "23:45.32"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "msSSS",
                "23:45.321"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "ms",
                "23:45"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "msS",
                "23:45.3\u2009\u2013\u200923:45.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "msSS",
                "23:45.32\u2009\u2013\u200923:45.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "msSSS",
                "23:45.321\u2009\u2013\u200923:45.987"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "ms",
                "23:45\u2009\u2013\u200923:46"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "msS",
                "23:45.3\u2009\u2013\u200923:46.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "msSS",
                "23:45.32\u2009\u2013\u200923:46.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "msSSS",
                "23:45.321\u2009\u2013\u200923:46.987"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "ms",
                "23:45\u2009\u2013\u200924:45"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "msS",
                "23:45.3\u2009\u2013\u200924:45.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "msSS",
                "23:45.32\u2009\u2013\u200924:45.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "msSSS",
                "23:45.321\u2009\u2013\u200924:45.987"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "s",
                "45"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "sS",
                "45.3"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "sSS",
                "45.32"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                "sSSS",
                "45.321"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "s",
                "45"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "sS",
                "45.3\u2009\u2013\u200945.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "sSS",
                "45.32\u2009\u2013\u200945.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 45),
                987,
                "sSSS",
                "45.321\u2009\u2013\u200945.987"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "s",
                "45\u2009\u2013\u200946"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "sS",
                "45.3\u2009\u2013\u200946.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "sSS",
                "45.32\u2009\u2013\u200946.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 1, 23, 46),
                987,
                "sSSS",
                "45.321\u2009\u2013\u200946.987"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "s",
                "45\u2009\u2013\u200945"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "sS",
                "45.3\u2009\u2013\u200945.9"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "sSS",
                "45.32\u2009\u2013\u200945.98"
            },
            {
                new Date(2019, 2, 10, 1, 23, 45),
                321,
                new Date(2019, 2, 10, 2, 24, 45),
                987,
                "sSSS",
                "45.321\u2009\u2013\u200945.987"
            },
        };

        Locale enLocale = Locale.ENGLISH;

        for (Object[] testCase : kTestCases) {
            DateIntervalFormat fmt = DateIntervalFormat.getInstance((String) testCase[4], enLocale);

            Date fromDate = (Date) testCase[0];
            long from = fromDate.getTime() + (Integer) testCase[1];
            Date toDate = (Date) testCase[2];
            long to = toDate.getTime() + (Integer) testCase[3];

            FormattedDateInterval res = fmt.formatToValue(new DateInterval(from, to));
            assertEquals("Formate for " + testCase[4], testCase[5], res.toString());
        }
    }

    @Test
    public void testTicket21222GregorianEraDiff() {
        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
        DateIntervalFormat g = DateIntervalFormat.getInstance("h", Locale.ENGLISH);
        g.setTimeZone(TimeZone.GMT_ZONE);

        cal.set(123, Calendar.APRIL, 5, 6, 0);
        Date date0123Apr5AD = cal.getTime();

        cal.set(Calendar.YEAR, 124);
        Date date0124Apr5AD = cal.getTime();

        cal.set(Calendar.ERA, GregorianCalendar.BC);
        Date date0124Apr5BC = cal.getTime();

        cal.set(Calendar.YEAR, 123);
        Date date0123Apr5BC = cal.getTime();

        DateInterval bothAD = new DateInterval(date0123Apr5AD.getTime(), date0124Apr5AD.getTime());
        DateInterval bothBC = new DateInterval(date0124Apr5BC.getTime(), date0123Apr5BC.getTime());
        DateInterval BCtoAD = new DateInterval(date0123Apr5BC.getTime(), date0124Apr5AD.getTime());

        FormattedDateInterval formatted = g.formatToValue(bothAD);
        assertEquals(
                "Gregorian - calendar both dates in AD",
                "4/5/123, 6\u202FAM\u2009\u2013\u20094/5/124, 6\u202FAM",
                formatted.toString());

        formatted = g.formatToValue(bothBC);
        assertEquals(
                "Gregorian - calendar both dates in BC",
                "4/5/124, 6\u202FAM\u2009\u2013\u20094/5/123, 6\u202FAM",
                formatted.toString());

        formatted = g.formatToValue(BCtoAD);
        assertEquals(
                "Gregorian - BC to AD",
                "4/5/123 BC, 6\u202FAM\u2009\u2013\u20094/5/124 AD, 6\u202FAM",
                formatted.toString());
    }

    private List<Field> getFields(FormattedDateInterval formatted) {
        List<Field> fields = new ArrayList<Field>();
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
        while (formatted.nextPosition(cfpos)) {
            fields.add(cfpos.getField());
        }
        return fields;
    }

    private void verifyFields(FormattedDateInterval formatted, List<Field> fields) {
        int i = 0;
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
        while (formatted.nextPosition(cfpos)) {
            assertEquals("Field", cfpos.getField(), fields.get(i));
            i++;
        }
    }

    @Test
    public void testTicket21222ROCEraDiff() {
        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
        DateIntervalFormat roc =
                DateIntervalFormat.getInstance("h", new ULocale("zh-Hant-TW@calendar=roc"));
        roc.setTimeZone(TimeZone.GMT_ZONE);

        // set date1910Jan2 to 1910/1/2 AD which is prior to MG
        cal.set(1910, Calendar.JANUARY, 2, 6, 0);
        Date date1910Jan2 = cal.getTime();

        // set date1911Jan2 to 1911/1/2 AD which is also prior to MG
        cal.set(Calendar.YEAR, 1911);
        Date date1911Jan2 = cal.getTime();

        // set date1912Jan2 to 1912/1/2 AD which is after MG
        cal.set(Calendar.YEAR, 1912);
        Date date1912Jan2 = cal.getTime();

        // set date1913Jan2 to 1913/1/2 AD which is also after MG
        cal.set(Calendar.YEAR, 1913);
        Date date1913Jan2 = cal.getTime();

        DateInterval bothBeforeMG =
                new DateInterval(date1910Jan2.getTime(), date1911Jan2.getTime());
        DateInterval beforeAfterMG =
                new DateInterval(date1911Jan2.getTime(), date1913Jan2.getTime());
        DateInterval bothAfterMG = new DateInterval(date1912Jan2.getTime(), date1913Jan2.getTime());

        FormattedDateInterval formatted = roc.formatToValue(bothAfterMG);
        assertEquals(
                "roc calendar - both dates in MG Era",
                "民國1/1/2上午6時\u2009\u2013\u2009民國2/1/2上午6時",
                formatted.toString());
        List<Field> expectedFields = getFields(formatted);

        formatted = roc.formatToValue(beforeAfterMG);
        assertEquals(
                "roc calendar - prior MG Era and in MG Era",
                "民國前1/1/2上午6時\u2009\u2013\u2009民國2/1/2上午6時",
                formatted.toString());
        verifyFields(formatted, expectedFields);

        formatted = roc.formatToValue(bothBeforeMG);
        assertEquals(
                "roc calendar - both dates prior MG Era",
                "民國前2/1/2上午6時\u2009\u2013\u2009民國前1/1/2上午6時",
                formatted.toString());
        verifyFields(formatted, expectedFields);
    }

    @Test
    public void testTicket21222JapaneseEraDiff() {
        Calendar cal = Calendar.getInstance(TimeZone.GMT_ZONE);
        DateIntervalFormat japanese =
                DateIntervalFormat.getInstance("h", new ULocale("ja@calendar=japanese"));
        japanese.setTimeZone(TimeZone.GMT_ZONE);

        cal.set(2019, Calendar.MARCH, 2, 6, 0);
        Date date2019Mar2 = cal.getTime();

        cal.set(Calendar.MONTH, Calendar.APRIL);
        cal.set(Calendar.DAY_OF_MONTH, 3);
        Date date2019Apr3 = cal.getTime();

        cal.set(Calendar.MONTH, Calendar.MAY);
        cal.set(Calendar.DAY_OF_MONTH, 4);
        Date date2019May4 = cal.getTime();

        cal.set(Calendar.MONTH, Calendar.JUNE);
        cal.set(Calendar.DAY_OF_MONTH, 5);
        Date date2019Jun5 = cal.getTime();

        DateInterval bothBeforeReiwa =
                new DateInterval(date2019Mar2.getTime(), date2019Apr3.getTime());
        DateInterval beforeAfterReiwa =
                new DateInterval(date2019Mar2.getTime(), date2019May4.getTime());
        DateInterval bothAfterReiwa =
                new DateInterval(date2019May4.getTime(), date2019Jun5.getTime());

        FormattedDateInterval formatted = japanese.formatToValue(bothAfterReiwa);
        assertEquals(
                "japanese calendar - both dates in Reiwa",
                "R1/5/4 午前6時～R1/6/5 午前6時",
                formatted.toString());
        List<Field> expectedFields = getFields(formatted);

        formatted = japanese.formatToValue(bothBeforeReiwa);
        assertEquals(
                "japanese calendar - both dates before Reiwa",
                "H31/3/2 午前6時～H31/4/3 午前6時",
                formatted.toString());
        verifyFields(formatted, expectedFields);

        formatted = japanese.formatToValue(beforeAfterReiwa);
        assertEquals(
                "japanese calendar - date before and in Reiwa",
                "H31/3/2 午前6時～R1/5/4 午前6時",
                formatted.toString());
        verifyFields(formatted, expectedFields);
    }

    @Test
    public void testTicket21939() {
        // the test here is just to check that this particular skeleton doesn't
        // lead to an IllegalArgumentException
        DateIntervalFormat dif =
                DateIntervalFormat.getInstance("rMdhm", ULocale.forLanguageTag("en-u-ca-chinese"));
        DateFormat df = dif.getDateFormat();
        SimpleDateFormat sdf = (SimpleDateFormat) df;
        assertEquals("Wrong date format", "M/d/r, h:mm\u202Fa", sdf.toPattern());

        // additional tests for the related ICU-22202
        dif = DateIntervalFormat.getInstance("Lh", ULocale.ENGLISH);
        df = dif.getDateFormat();
        sdf = (SimpleDateFormat) df;
        assertEquals("Wrong date format", "L, h a", sdf.toPattern());

        dif = DateIntervalFormat.getInstance("UH", ULocale.forLanguageTag("en-u-ca-chinese"));
        df = dif.getDateFormat();
        sdf = (SimpleDateFormat) df;
        assertEquals("Wrong date format", "r(U), HH", sdf.toPattern());
    }

    @Test
    public void testTicket20710_FieldIdentity() {
        DateIntervalFormat dtifmt =
                DateIntervalFormat.getInstance("eeeeMMMddyyhhmma", new ULocale("de-CH"));
        Calendar calendar1 = Calendar.getInstance(TimeZone.getTimeZone("CET"));
        calendar1.setTimeInMillis(1563235200000l);
        Calendar calendar2 = Calendar.getInstance(TimeZone.getTimeZone("CET"));
        calendar2.setTimeInMillis(1564235200000l);

        {
            FormattedDateInterval fv = dtifmt.formatToValue(calendar1, calendar2);
            ConstrainedFieldPosition cfp = new ConstrainedFieldPosition();
            cfp.constrainClass(DateIntervalFormat.SpanField.class);
            assertTrue("Span field should be in non-identity formats", fv.nextPosition(cfp));
        }
        {
            FormattedDateInterval fv = dtifmt.formatToValue(calendar1, calendar1);
            ConstrainedFieldPosition cfp = new ConstrainedFieldPosition();
            cfp.constrainClass(DateIntervalFormat.SpanField.class);
            assertFalse("Span field should not be in identity formats", fv.nextPosition(cfp));
        }
    }

    @Test
    public void testTicket20710_IntervalIdentity() {
        boolean quick = getExhaustiveness() <= 5;

        String timeZone = "PST";
        ULocale[] locales = ULocale.getAvailableLocales();
        String[] skeletons = {
            "EEEEMMMMdyhmmssazzzz",
            "EEEEMMMMdyhhmmssazzzz",
            "EEEEMMMMddyyyyhhmmssvvvva",
            "EEEEMMMMddhmszza",
            "EEMMMMddyyhhzza",
            "eeeeMMMddyyhhmma",
            "MMddyyyyhhmmazzzz",
            "hhmmazzzz",
            "hmmssazzzz",
            "hhmmsszzzz",
            "MMddyyyyhhmmzzzz"
        };

        ULocale[] quickLocales = {
            new ULocale("en"), new ULocale("es"), new ULocale("sr"), new ULocale("zh"),
        };
        if (quick) {
            locales = quickLocales;
        }

        for (int i = 0; i < locales.length; i++) {
            ULocale locale = locales[i];
            DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(locale);
            Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
            calendar.setTimeInMillis(1563235200000l);
            for (String skeleton : skeletons) {
                DateIntervalFormat dtifmt = DateIntervalFormat.getInstance(skeleton, locale);

                FieldPosition pos = DontCareFieldPosition.INSTANCE;
                StringBuffer resultIntervalFormat = new StringBuffer();
                dtifmt.format(calendar, calendar, resultIntervalFormat, pos);

                String pattern = gen.getBestPattern(skeleton);
                SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, locale);

                StringBuffer resultDateFormat = new StringBuffer();
                dateFormat.format(calendar, resultDateFormat, pos);
                assertEquals(
                        "DateIntervalFormat should fall back to DateFormat in the identity format",
                        resultDateFormat.toString(),
                        resultIntervalFormat.toString());
            }
        }
    }
}
